﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Linq;
using Sausage.Common;
using Sausage.Web.DataModel;
using Sausage.Web.Models;
using Sausage.Web.Code;
using Telerik.Web.Mvc;

namespace Sausage.Web.Domain
{
    public class UserHelper
    {
        /// <summary>
        /// 根据指定的登录名获得用户信息。
        /// </summary>
        /// <param name="loginName">用户的登录名。</param>
        /// <returns>根据指定的登录名获得的用户信息。</returns>
        /// <remarks></remarks>
        public static User GetUserByLoginName(string loginName)
        {
            using (var context = new SausageEntities())
            {
                return context.User.Include("UserRole").Include("Organization").FirstOrDefault(user => 0 == string.Compare(user.LoginName, loginName, true));
            }
        }

        public static User GetUserByID(Guid userID)
        {
            using (var context = new SausageEntities())
            {
                return context.User.Include("UserRole").Include("Organization").FirstOrDefault(user => user.UserID == userID);
            }
        }

        public static List<User> GetUserList()
        {
            using (var context = new SausageEntities())
            {
                return context.User.ToList();
            }
        }

        public static void DeleteUser(Guid userID)
        {
            using (var context = new SausageEntities())
            {
                //Delete the User Role
                var roles = context.UserRole.Where(userRole => userRole.UserID == userID).ToList();
                foreach (var userRole in roles)
                {
                    context.CreateObjectSet<UserRole>().Attach(userRole);
                    context.ObjectStateManager.ChangeObjectState(userRole, EntityState.Deleted);
                }

                //Delete the User
                var user = new User { UserID = userID };
                context.CreateObjectSet<User>().Attach(user);
                context.ObjectStateManager.ChangeObjectState(user, EntityState.Deleted);

                context.SaveChanges();
            }
        }

        public static void ResetPassword(Guid userID)
        {
            using (var context = new SausageEntities())
            {
                var target = context.User.FirstOrDefault(user => user.UserID == userID);

                if (target == null)
                    return;

                target.Password = PasswordHash.GetHashedPasswordBase64(Utility.DefaultPassword);
                target.MustChangePassword = true;
                context.SaveChanges();
            }
        }

        public static void UpdateUser(AccountDetail data)
        {
            using (var context = new SausageEntities())
            {
                var target = context.User.FirstOrDefault(user => user.UserID == data.UserID);
                if (target == null)
                    return;

                target.OrganizationID = data.OrganizationID;
                target.UserName = data.UserName;
                target.LoginName = data.LoginName;
                target.IsEnabled = data.IsEnabled;
                target.Memo = data.Memo;

                //Delete current role.
                var roles = context.UserRole.Where(userRole => userRole.UserID == data.UserID).ToList();
                foreach (var userRole in roles)
                {
                    context.CreateObjectSet<UserRole>().Attach(userRole);
                    context.ObjectStateManager.ChangeObjectState(userRole, EntityState.Deleted);
                }

                //Add new user role.
                var isSystemAdmin = Helper.CurrentPrincipal.IsInRole("SystemAdmin");
                foreach (var roleID in data.Roles)
                {
                    if (!isSystemAdmin && !Helper.CurrentPrincipal.RoleIDList.Contains(roleID))
                        continue; // the creator do not have the role.

                    var userRole = new UserRole();
                    userRole.UserRoleID = Guid.NewGuid();
                    userRole.UserID = data.UserID;
                    userRole.RoleID = roleID;
                    context.AddToUserRole(userRole);
                }
                context.SaveChanges();
            }
        }

        public static void CreateUser(AccountDetail data)
        {
            using (var context = new SausageEntities())
            {
                var user = new User();

                //1. add the user.
                user.UserID = Guid.NewGuid();
                user.OrganizationID = data.OrganizationID;
                user.UserName = data.UserName;
                user.LoginName = data.LoginName;
                user.IsBuildin = data.IsBuildin;
                user.IsEnabled = data.IsEnabled;
                user.Memo = data.Memo;
                user.Password = PasswordHash.GetHashedPasswordBase64(data.Password);
                context.AddToUser(user);

                var isSystemAdmin = Helper.CurrentPrincipal.IsInRole("SystemAdmin");

                //2. add the role.
                if (data.Roles != null)
                {
                    foreach (var roleID in data.Roles)
                    {
                        if (!isSystemAdmin && !Helper.CurrentPrincipal.RoleIDList.Contains(roleID))
                            continue; // the creator do not have the role.

                        var userRole = new UserRole();
                        userRole.UserRoleID = Guid.NewGuid();
                        userRole.UserID = user.UserID;
                        userRole.RoleID = roleID;
                        context.AddToUserRole(userRole);
                    }
                }

                context.SaveChanges();
            }
        }

        public static GridModel<AccountListRow> QueryUser(JosnPagingQueryModel query)
        {
            Guid targetID;
            var isWithChild = Helper.IsNeedOrganizationQuery(query, out targetID);
            List<Guid> organization = OrganizationHelper.GetAllowedOrganizationList(isWithChild, targetID);

            using (var context = new SausageEntities())
            {
                var result = UIHelper.GetGridModelFromQueryModel<User>(
                     context.User.Where(user => organization.Contains(user.OrganizationID)),
                     query.page,
                     query.limit,
                     GetSortDescriptorFromQueryModel(query.SortModel),
                     GetSearchFilterFromQueryModel(query.FilterModel, isWithChild));

                var list = result.Data.Select(user => new AccountListRow()
                {
                    UserID = user.UserID,
                    UserName = user.UserName,
                    LoginName = user.LoginName,
                    IsBuildin = user.IsBuildin,
                    IsEnabled = user.IsEnabled,
                    LastLoginTime = user.LastLoginTime,
                    Memo = user.Memo,
                    Organization = user.Organization.OrganizationName,
                    IsAllowDelay = user.IsAllowDelay,
                    DelayExpiration = user.DelayExpiration,
                    DelayBeginDate = user.DelayBeginDate,
                    DelayEndDate = user.DelayEndDate
                }).ToList<AccountListRow>();

                return new GridModel<AccountListRow>()
                {
                    Aggregates = result.Aggregates,
                    Data = list,
                    Total = result.Total
                };
            }
        }

        public static void UpdateDelaySubmitSetting(AccountDelaySubmitSetting data)
        {
            //判断当前用户类型
            if (Helper.CurrentPrincipal.User.Organization.Category != 0)
            {
                //如果不是总段用户，则不允许设置
                return;
            }

            using (var context = new SausageEntities())
            {
                //循环处理
                foreach (Guid id in data.Users)
                {
                    //查询用户信息
                    User entity = context.User.FirstOrDefault(user => user.UserID == id);

                    //判断是否存在
                    if (null != entity)
                    {
                        //需要计算过期时间
                        entity.DelayBeginDate = data.DelayBeginDate;
                        entity.DelayEndDate = data.DelayEndDate;
                        entity.IsAllowDelay = data.IsAllowDelay;
                        entity.DelayExpiration = DateTime.Now.AddDays(1);
                    }
                }

                //保存变化
                context.SaveChanges();
            }
        }

        private static List<IFilterDescriptor> GetSearchFilterFromQueryModel(IEnumerable<JosnQueryFilterModel> filterModels, bool isWithChild)
        {
            var filterList = new List<IFilterDescriptor>();
            foreach (var item in filterModels)
            {
                if (string.IsNullOrEmpty(item.value))
                    continue;

                if (item.property == "OrganizationID" && isWithChild)
                    continue;

                if (item.property == "OrganizationID")
                {
                    var organizationID = Guid.Parse(item.value);
                    if (organizationID != Guid.Empty)
                        filterList.Add(new FilterDescriptor(item.property, FilterOperator.IsEqualTo, organizationID));
                }
                else //other filter.
                    filterList.Add(new FilterDescriptor(item.property, FilterOperator.Contains, item.value));
            }
            return filterList;
        }

        private static List<SortDescriptor> GetSortDescriptorFromQueryModel(IEnumerable<JosnQuerySortModel> sortModels)
        {
            //convert the sort description.
            var sortList = new List<SortDescriptor>();
            foreach (var item in sortModels)
            {
                sortList.Add(new SortDescriptor()
                {
                    Member = item.property == "Organization" ? "Organization.OrganizationName" : item.property,
                    SortDirection = item.direction.ToLower() == "desc" ? ListSortDirection.Descending : ListSortDirection.Ascending
                });
            }
            return sortList;
        }

        public static void UserLastLogin(User user)
        {
            using (var context = new SausageEntities())
            {
                var target = context.User.FirstOrDefault(item => item.UserID == user.UserID);
                target.LastLoginTime = DateTime.Now;
                context.SaveChanges();
            }
        }

        public static void ChangePassword(Guid userID, string password)
        {
            using (var context = new SausageEntities())
            {

                var target = context.User.FirstOrDefault(user => user.UserID == userID);
                if (target == null)
                    return;

                target.Password = PasswordHash.GetHashedPasswordBase64(password);
                target.MustChangePassword = false;
                context.SaveChanges();
            }
        }
    }
}